# Not sure if necessary... was an issue with a version conflict... try new version in the future again...
# devtools::install_version("RPostgres", version = "1.2.1", repos = "http://cran.us.r-project.org")

### general options
Sys.setenv(LANG = "en")
options("scipen" = 100, "digits" = 4) # override R's tendency to use scientific notation

### Clean workspace
rm(list=ls())
graphics.off()

### Load packages (maybe need to be installed first)
# Standard
library(tidyverse) # General DS toolkit
library(magrittr) # For advanced piping

# Databases
library(DBI) # GEneral R database interface
library(RPostgres) # PostgreSQL interface driver 
library(dbplyr) # for dplyr with databases

# networks
library(tidygraph)
library(ggraph)
library(ggrepel)

# Load functions
source("functions/functions_relatedness.R")
# Load script with variables
source("../variables.R")

# set up connection to existing PostgreSQL database, just plug in own details
con <- dbConnect(drv = RPostgres::Postgres(), 
                 dbname = var_dbname,
                 host = var_host, 
                 port = var_port,
                 user = var_user, 
                 password = var_password,
                 sslmode = 'require'
                 )

rm(var_dbname, var_host, var_password, var_port, var_user)

1 Introduction

  • In this notebook, we present the first results of an analysis of green development paths of Nordic regions
  • It is based on patent data from 1990-2015 (PATSTAT, Autumn 2021 Edition)
  • Analysis is done on all Nordic NUTS 2 regions (fractionalized patent allocation by inventor location, DOCDB family level)
  • Industries are captured by NACE2 codes of patents according to the OECD IPC-NACE2 concordance table.
  • Green patents are identified using the Y02 tag in the CPC classification

1.1 Preprocessing

# con %>% dbListTables() %>% sort()
## LOAD DATA

# Regular tables
data_appln <- read_rds('../temp/data_appln.rds')
data_docdb_fam_cpc <- read_rds('../temp/data_docdb_fam_cpc.rds')
data_pers_appln  <- read_rds('../temp/data_pers_appln.rds')
data_person <- read_rds('../temp/data_person.rds')
data_nace2 <- read_rds('../temp/data_nace2.rds')

# Adittional ones
g_tech <- read_rds('../temp/g_tech.rds')
region_RTA <- read_rds('../temp/region_RTA.rds')
region_tech <- read_rds('../temp/region_tech.rds')
## Defining parameters
n_regions = 10
cuttoff = 50
# Select region
select_regions <- region_tech %>%
  group_by(nuts) %>%
  summarise(n = sum(weight_frac, na.rm = TRUE),
            n_Y = sum(weight_frac * Y_tag, na.rm = TRUE)) %>%
  ungroup() %>%
  mutate(share_Y = n_Y / (n + n_Y)) %>%
  filter(nuts %in% c('SE232', 'NO043', 'DK012')) %>%
  arrange(desc(n_Y))
# Restrict to top N regions
top_regions <- region_tech %>%
  group_by(nuts) %>%
  summarise(n = sum(weight_frac, na.rm = TRUE),
            n_Y = sum(weight_frac * Y_tag, na.rm = TRUE)) %>%
  ungroup() %>%
  mutate(share_Y = n_Y / (n + n_Y)) %>%
  #filter(n_Y >= cuttoff ) %>%
  arrange(desc(n_Y)) %>%
  slice(1:n_regions) %>%
  bind_rows(select_regions) %>%
  distinct()
# Createdataframe with technology relatedness edgelist
tech_rel <- g_tech %E>%
  mutate(from_nace = .N()$name[from],
         to_nace = .N()$name[to]) %>%
  as_tibble() %>%
  mutate(from = from_nace %>% as.character(),
         to = to_nace %>% as.character(),
         pct_rank = weight %>% percent_rank()) %>%
  arrange(from, to) 

tech_rel %<>%
  bind_rows(tech_rel %>% 
              rename(from_new = to, to_new = from) %>% 
              rename(from = from_new, to = to_new) %>%
              relocate(from, to)) %>%
  distinct(from, to, .keep_all = TRUE)
# augment regions data 
# NOTE: DO earlier already in construction
region_RTA %<>%
  mutate(country = nuts %>% str_sub(1,2)) 
# Summarize Regions
region_RTA_agg <- region_RTA %>%
  group_by(nuts, period, Y_tag) %>%
  summarise(n_spec = rta_bin %>% sum(na.rm = TRUE),
            n_spec_count = (n_tech_region * rta_bin) %>% sum(na.rm = TRUE),
            HHI = sum((n_tech_region/sum(n_tech_region) * 100)^2) ) %>%
  ungroup() %>%
  mutate(country = nuts %>% str_sub(1,2),
    nuts_period = paste(nuts, 'P', period)) 
`summarise()` has grouped output by 'nuts', 'period'. You can override using the `.groups` argument.

2 Patent application development

  • In the following, a brief descriptive analysis of the development of green and non-green patent application in the Nordics
  • In addition, a breackdown of green patents by top green patenting reagions
# Dataframe with regions and technology fields
tech_dev <- region_RTA %>%
  select(period, country, nuts, nace_group, Y_tag, n_tech_region, rta, rta_bin) %>%
  arrange(nuts, nace_group, Y_tag, period) 

tech_dev %<>% 
  group_by(nuts, nace_group, Y_tag) %>%
  mutate(rta_dev = case_when(
    rta_bin < lag(rta_bin, 1)  ~ -1,
    rta_bin == lag(rta_bin, 1)  ~ 0,
    rta_bin > lag(rta_bin, 1)  ~ 1 
  )) %>%
  ungroup()
data_appln %>%
  count(appln_filing_year, Y_tag) %>%
  ggplot(aes(x = appln_filing_year, y = n, col = Y_tag)) + 
  geom_line(key_glyph = "timeseries") +
  labs(title = 'Patent applications: Development',
       subtitle = 'All Nordic contries, by Y tag',
       x = 'Year',
       y = 'Number applications',
       col = 'Green')

3 Technology space general

  • We calculate the relatedness of industries by co-occurence pattern following Hidalgo & Hausmann (2007)
  • Revealed technological advantage (RTA) Is sepperatedly calculated for Y-tag and non-Y-tag patents.
data_pers_appln %>%
  semi_join(top_regions, by = 'nuts') %>%
  count(appln_filing_year, nuts, Y_tag, wt = weight_frac) %>%
  ggplot(aes(x = appln_filing_year, y = n, col = nuts)) + 
  geom_line(key_glyph = "timeseries") +
  facet_wrap(vars(Y_tag), scales = 'free') +
  labs(title = 'Patent applications: Development',
       subtitle = 'All Nordic contries',
       x = 'Year',
       y = 'Number applications, by region and Y tag',
       col = 'Nuts3')

set.seed(1337)
coords_tech <- g_tech %>% igraph::layout.fruchterman.reingold() %>% as_tibble()
colnames(coords_tech) <- c("x", "y")

4 Regional specialization (RTA) development

  • Comparison of specialization provides in period 1 and 2
g_tech %N>%
  mutate(nace_group_name = nace_group_name %>% str_trunc(50, side = 'right')) %>%
  ggraph(layout =  coords_tech) + 
  geom_edge_link(aes(width = weight, alpha = weight), colour = "grey") + 
  geom_node_point(aes(colour = nace_sec_name, size = dgr)) + 
  geom_node_text(aes(label = nace_group_name, size = dgr, filter = percent_rank(dgr) >= 0.5 ), repel = TRUE) +
  theme_void() +
  theme(legend.position="bottom") + 
  labs(title = 'Industry Space (all Nordics)',
       subtitle = 'Nodes = NACE 2 Industries. Edges: Relatedness')

p1 <- region_RTA_agg  %>%
  semi_join(top_regions, by = 'nuts') %>%
  pivot_wider(names_from = Y_tag, values_from = c(n_spec, n_spec_count, HHI), values_fill = 0, names_prefix = 'Y_tag_') 

p2 <- p1 %>% 
  select(period, nuts, n_spec_Y_tag_FALSE, n_spec_Y_tag_TRUE) %>%
  pivot_wider(names_from = period, values_from = c(n_spec_Y_tag_FALSE, n_spec_Y_tag_TRUE))
p1 %>%
  ggplot(aes(x = n_spec_Y_tag_FALSE, y = n_spec_Y_tag_TRUE)) +
  geom_point(aes(size = n_spec_count_Y_tag_TRUE, col = HHI_Y_tag_TRUE)) +
  geom_text(aes(label = nuts), position = position_dodge(0.9), alpha = 0.75) +
  geom_segment(data = p2, 
               aes(x = n_spec_Y_tag_FALSE_1,
                   y = n_spec_Y_tag_TRUE_1,
                   xend = n_spec_Y_tag_FALSE_2,
                   yend = n_spec_Y_tag_TRUE_2,
                   size = 1),
               alpha = 0.15,
               arrow = arrow(length = unit(0.5, "cm"), type = "closed"),
               show.legend = FALSE) +
  scale_color_gradient2(low = "skyblue", mid = 'yellow', high = "red", midpoint = 1) +
  labs(title = 'Development of new regional specializations', 
       subtitle = 'By number of green and non green specializations in period 1 and 2',
       note = '',
       x = 'N non-green specializations',
       y = 'N green specializations',
       size = 'N green patents',
       col = 'HHI green patents') 

5 Analysis for existing green paths:

rm(p2, p2)
Warning: object 'p2' not found
select_regions_green <- tech_dev %>%
  group_by(nuts, period) %>%
  summarise(green =  sum(Y_tag * rta, na.rm = TRUE),
            green_bin =  sum(Y_tag * rta_bin, na.rm = TRUE),
            n_tech_region =  sum(n_tech_region, na.rm = TRUE),
            n_green_region =  sum(Y_tag * n_tech_region, na.rm = TRUE),
            n_green_rta =  sum(Y_tag * n_tech_region * rta_bin, na.rm = TRUE)) %>%
  ungroup() %>%
  filter(n_green_rta >= 100,
         green_bin >= 1,
         period == '1') %>%
  select(nuts)
`summarise()` has grouped output by 'nuts'. You can override using the `.groups` argument.
tech_spec_dev <- tech_dev %>%
  filter(n_tech_region >= 50) %>%
  group_by(nuts, Y_tag) %>%
  summarise(rta_dev = rta_dev %>% sum(na.rm = TRUE)) %>%
  ungroup() %>%
  pivot_wider(names_from = Y_tag, values_from = rta_dev, values_fill = 0, names_prefix = 'Y_spec_')
`summarise()` has grouped output by 'nuts'. You can override using the `.groups` argument.
tech_rel_dev <- tech_rel %>% 
  select(from, to, weight) %>%
  left_join(tech_dev %>% distinct(nace_group, nuts), by = c('from' = 'nace_group')) %>%
  # filter for rta in period 1
  inner_join(tech_dev %>% filter(period == '1', rta_bin == 1) %>% select(nace_group, nuts, Y_tag), by = c('to' = 'nace_group', 'nuts')) %>%
  # filter for new green specialization in period 2
  semi_join(tech_dev %>% filter(period == '2', rta_bin == 1, rta_dev == 1, Y_tag == TRUE), by = c('from' = 'nace_group', 'nuts')) %>%
  rename(nace_group = from, related_techn = to) %>%
  group_by(nuts, nace_group, Y_tag) %>%
  summarise(rel_max = weight %>% max(),
            rel_sum = weight %>% sum(),
            rel_mean = weight %>% mean()) %>%
  ungroup()
`summarise()` has grouped output by 'nuts', 'nace_group'. You can override using the `.groups` argument.
tech_rel_dev %>%
  group_by(nuts, Y_tag) %>%
  summarise(rel = rel_max %>% mean()) %>%
  ungroup() %>%
  pivot_wider(names_from = Y_tag, values_from = rel, names_prefix = 'Y_', values_fill = 0) %>%
  left_join(tech_dev %>% filter(Y_tag == TRUE, period == '2', rta_bin == 1) %>% select(nuts , n_tech_region) %>% count(nuts, wt = n_tech_region), by = c('nuts')) %>%
  mutate(country = nuts %>% str_sub(1,2)) %>%
  #semi_join(top_regions, by = 'nuts') %>%
  filter(0.5 <= percent_rank(n)) %>%
  ggplot(aes(x = Y_FALSE, y = Y_TRUE, size = n)) +
  geom_point(aes(col = country)) +
  geom_text_repel(aes(label = nuts), box.padding = 0.5, max.overlaps = Inf) +
  theme(legend.position="bottom") + 
    labs(title = 'New green specialization period 2', 
       subtitle = 'By nuts regions',
       note = 'Relatedness is the mean over all new green specializations, per green specialization largest relatedness to former specialization counted',
       x = 'Relatedness non-green',
       y = 'Relatedness green',
       size = 'N green patents') 
`summarise()` has grouped output by 'nuts'. You can override using the `.groups` argument.

6 TODO

tech_rel_dev %>%
  group_by(nuts, nace_group, Y_tag) %>%
  summarise(rel = rel_max %>% mean()) %>%
  ungroup() %>%
  pivot_wider(names_from = Y_tag, values_from = rel, names_prefix = 'Y_', values_fill = 0) %>%
  left_join(tech_dev %>% filter(Y_tag == TRUE, period == '2', rta_bin == 1) %>% select(nuts, nace_group, n_tech_region) %>% count(nuts, nace_group, wt = n_tech_region), by = c('nuts', 'nace_group')) %>%
  mutate(country = nuts %>% str_sub(1,2)) %>%
  semi_join(top_regions, by = 'nuts') %>%
  ggplot(aes(x = Y_FALSE, y = Y_TRUE, size = n)) +
  geom_point() +
  geom_text_repel(aes(label = nace_group), box.padding = 0.5) +
  facet_wrap(vars(nuts)) +
    labs(title = 'New green specialization period 2', 
       subtitle = 'By nuts regions',
       note = 'Relatedness is the mean over all new green specializations, per green specialization largest relatedness to former specialization counted',
       x = 'Relatedness non-green',
       y = 'Relatedness green',
       size = 'N green patents') 
`summarise()` has grouped output by 'nuts', 'nace_group'. You can override using the `.groups` argument.

LS0tCnRpdGxlOiAnR3JlZW4gUmVnaW9uYWwgUGF0aCBwYXBlcjogRmlyc3QgcmVzdWx0cycKYXV0aG9yOiAiRGFuaWVsIFMuIEhhaW4iCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVCLCAlWScpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBkZl9wcmludDogcGFnZWQKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDMKICAgIHRvY19mbG9hdDogeWVzCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgY29kZV9mb2xkaW5nOiBoaWRlCi0tLQoKCmBgYHtyLCBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBOb3Qgc3VyZSBpZiBuZWNlc3NhcnkuLi4gd2FzIGFuIGlzc3VlIHdpdGggYSB2ZXJzaW9uIGNvbmZsaWN0Li4uIHRyeSBuZXcgdmVyc2lvbiBpbiB0aGUgZnV0dXJlIGFnYWluLi4uCiMgZGV2dG9vbHM6Omluc3RhbGxfdmVyc2lvbigiUlBvc3RncmVzIiwgdmVyc2lvbiA9ICIxLjIuMSIsIHJlcG9zID0gImh0dHA6Ly9jcmFuLnVzLnItcHJvamVjdC5vcmciKQoKIyMjIGdlbmVyYWwgb3B0aW9ucwpTeXMuc2V0ZW52KExBTkcgPSAiZW4iKQpvcHRpb25zKCJzY2lwZW4iID0gMTAwLCAiZGlnaXRzIiA9IDQpICMgb3ZlcnJpZGUgUidzIHRlbmRlbmN5IHRvIHVzZSBzY2llbnRpZmljIG5vdGF0aW9uCgojIyMgQ2xlYW4gd29ya3NwYWNlCnJtKGxpc3Q9bHMoKSkKZ3JhcGhpY3Mub2ZmKCkKCiMjIyBMb2FkIHBhY2thZ2VzIChtYXliZSBuZWVkIHRvIGJlIGluc3RhbGxlZCBmaXJzdCkKIyBTdGFuZGFyZApsaWJyYXJ5KHRpZHl2ZXJzZSkgIyBHZW5lcmFsIERTIHRvb2xraXQKbGlicmFyeShtYWdyaXR0cikgIyBGb3IgYWR2YW5jZWQgcGlwaW5nCgojIERhdGFiYXNlcwpsaWJyYXJ5KERCSSkgIyBHRW5lcmFsIFIgZGF0YWJhc2UgaW50ZXJmYWNlCmxpYnJhcnkoUlBvc3RncmVzKSAjIFBvc3RncmVTUUwgaW50ZXJmYWNlIGRyaXZlciAKbGlicmFyeShkYnBseXIpICMgZm9yIGRwbHlyIHdpdGggZGF0YWJhc2VzCgojIG5ldHdvcmtzCmxpYnJhcnkodGlkeWdyYXBoKQpsaWJyYXJ5KGdncmFwaCkKbGlicmFyeShnZ3JlcGVsKQoKIyBMb2FkIGZ1bmN0aW9ucwpzb3VyY2UoImZ1bmN0aW9ucy9mdW5jdGlvbnNfcmVsYXRlZG5lc3MuUiIpCmBgYAoKYGBge3J9CiMgTG9hZCBzY3JpcHQgd2l0aCB2YXJpYWJsZXMKc291cmNlKCIuLi92YXJpYWJsZXMuUiIpCgojIHNldCB1cCBjb25uZWN0aW9uIHRvIGV4aXN0aW5nIFBvc3RncmVTUUwgZGF0YWJhc2UsIGp1c3QgcGx1ZyBpbiBvd24gZGV0YWlscwpjb24gPC0gZGJDb25uZWN0KGRydiA9IFJQb3N0Z3Jlczo6UG9zdGdyZXMoKSwgCiAgICAgICAgICAgICAgICAgZGJuYW1lID0gdmFyX2RibmFtZSwKICAgICAgICAgICAgICAgICBob3N0ID0gdmFyX2hvc3QsIAogICAgICAgICAgICAgICAgIHBvcnQgPSB2YXJfcG9ydCwKICAgICAgICAgICAgICAgICB1c2VyID0gdmFyX3VzZXIsIAogICAgICAgICAgICAgICAgIHBhc3N3b3JkID0gdmFyX3Bhc3N3b3JkLAogICAgICAgICAgICAgICAgIHNzbG1vZGUgPSAncmVxdWlyZScKICAgICAgICAgICAgICAgICApCgpybSh2YXJfZGJuYW1lLCB2YXJfaG9zdCwgdmFyX3Bhc3N3b3JkLCB2YXJfcG9ydCwgdmFyX3VzZXIpCmBgYAoKYGBge3J9CiMgY29uICU+JSBkYkxpc3RUYWJsZXMoKSAlPiUgc29ydCgpCmBgYAoKIyBJbnRyb2R1Y3Rpb24KCiogSW4gdGhpcyBub3RlYm9vaywgd2UgcHJlc2VudCB0aGUgZmlyc3QgcmVzdWx0cyBvZiBhbiBhbmFseXNpcyBvZiBncmVlbiBkZXZlbG9wbWVudCBwYXRocyBvZiBOb3JkaWMgcmVnaW9ucwoqIEl0IGlzIGJhc2VkIG9uIHBhdGVudCBkYXRhIGZyb20gMTk5MC0yMDE1IChQQVRTVEFULCBBdXR1bW4gMjAyMSBFZGl0aW9uKQoqIEFuYWx5c2lzIGlzIGRvbmUgb24gYWxsIE5vcmRpYyBOVVRTIDIgcmVnaW9ucyAoZnJhY3Rpb25hbGl6ZWQgcGF0ZW50IGFsbG9jYXRpb24gYnkgaW52ZW50b3IgbG9jYXRpb24sIERPQ0RCIGZhbWlseSBsZXZlbCkKKiBJbmR1c3RyaWVzIGFyZSBjYXB0dXJlZCBieSBOQUNFMiBjb2RlcyBvZiBwYXRlbnRzIGFjY29yZGluZyB0byB0aGUgT0VDRCBJUEMtTkFDRTIgY29uY29yZGFuY2UgdGFibGUuCiogR3JlZW4gcGF0ZW50cyBhcmUgaWRlbnRpZmllZCB1c2luZyB0aGUgWTAyIHRhZyBpbiB0aGUgQ1BDIGNsYXNzaWZpY2F0aW9uCgojIyBQcmVwcm9jZXNzaW5nIAoKYGBge3J9CiMjIExPQUQgREFUQQoKIyBSZWd1bGFyIHRhYmxlcwpkYXRhX2FwcGxuIDwtIHJlYWRfcmRzKCcuLi90ZW1wL2RhdGFfYXBwbG4ucmRzJykKZGF0YV9kb2NkYl9mYW1fY3BjIDwtIHJlYWRfcmRzKCcuLi90ZW1wL2RhdGFfZG9jZGJfZmFtX2NwYy5yZHMnKQpkYXRhX3BlcnNfYXBwbG4gIDwtIHJlYWRfcmRzKCcuLi90ZW1wL2RhdGFfcGVyc19hcHBsbi5yZHMnKQpkYXRhX3BlcnNvbiA8LSByZWFkX3JkcygnLi4vdGVtcC9kYXRhX3BlcnNvbi5yZHMnKQpkYXRhX25hY2UyIDwtIHJlYWRfcmRzKCcuLi90ZW1wL2RhdGFfbmFjZTIucmRzJykKCiMgQWRpdHRpb25hbCBvbmVzCmdfdGVjaCA8LSByZWFkX3JkcygnLi4vdGVtcC9nX3RlY2gucmRzJykKcmVnaW9uX1JUQSA8LSByZWFkX3JkcygnLi4vdGVtcC9yZWdpb25fUlRBLnJkcycpCnJlZ2lvbl90ZWNoIDwtIHJlYWRfcmRzKCcuLi90ZW1wL3JlZ2lvbl90ZWNoLnJkcycpCmBgYAoKCmBgYHtyfQojIyBEZWZpbmluZyBwYXJhbWV0ZXJzCm5fcmVnaW9ucyA9IDEwCmN1dHRvZmYgPSA1MApgYGAKCmBgYHtyfQojIFNlbGVjdCByZWdpb24Kc2VsZWN0X3JlZ2lvbnMgPC0gcmVnaW9uX3RlY2ggJT4lCiAgZ3JvdXBfYnkobnV0cykgJT4lCiAgc3VtbWFyaXNlKG4gPSBzdW0od2VpZ2h0X2ZyYWMsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIG5fWSA9IHN1bSh3ZWlnaHRfZnJhYyAqIFlfdGFnLCBuYS5ybSA9IFRSVUUpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKHNoYXJlX1kgPSBuX1kgLyAobiArIG5fWSkpICU+JQogIGZpbHRlcihudXRzICVpbiUgYygnU0UyMzInLCAnTk8wNDMnLCAnREswMTInKSkgJT4lCiAgYXJyYW5nZShkZXNjKG5fWSkpCmBgYAoKYGBge3J9CiMgUmVzdHJpY3QgdG8gdG9wIE4gcmVnaW9ucwp0b3BfcmVnaW9ucyA8LSByZWdpb25fdGVjaCAlPiUKICBncm91cF9ieShudXRzKSAlPiUKICBzdW1tYXJpc2UobiA9IHN1bSh3ZWlnaHRfZnJhYywgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgbl9ZID0gc3VtKHdlaWdodF9mcmFjICogWV90YWcsIG5hLnJtID0gVFJVRSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoc2hhcmVfWSA9IG5fWSAvIChuICsgbl9ZKSkgJT4lCiAgI2ZpbHRlcihuX1kgPj0gY3V0dG9mZiApICU+JQogIGFycmFuZ2UoZGVzYyhuX1kpKSAlPiUKICBzbGljZSgxOm5fcmVnaW9ucykgJT4lCiAgYmluZF9yb3dzKHNlbGVjdF9yZWdpb25zKSAlPiUKICBkaXN0aW5jdCgpCmBgYAoKYGBge3J9CiMgQ3JlYXRlZGF0YWZyYW1lIHdpdGggdGVjaG5vbG9neSByZWxhdGVkbmVzcyBlZGdlbGlzdAp0ZWNoX3JlbCA8LSBnX3RlY2ggJUU+JQogIG11dGF0ZShmcm9tX25hY2UgPSAuTigpJG5hbWVbZnJvbV0sCiAgICAgICAgIHRvX25hY2UgPSAuTigpJG5hbWVbdG9dKSAlPiUKICBhc190aWJibGUoKSAlPiUKICBtdXRhdGUoZnJvbSA9IGZyb21fbmFjZSAlPiUgYXMuY2hhcmFjdGVyKCksCiAgICAgICAgIHRvID0gdG9fbmFjZSAlPiUgYXMuY2hhcmFjdGVyKCksCiAgICAgICAgIHBjdF9yYW5rID0gd2VpZ2h0ICU+JSBwZXJjZW50X3JhbmsoKSkgJT4lCiAgYXJyYW5nZShmcm9tLCB0bykgCgp0ZWNoX3JlbCAlPD4lCiAgYmluZF9yb3dzKHRlY2hfcmVsICU+JSAKICAgICAgICAgICAgICByZW5hbWUoZnJvbV9uZXcgPSB0bywgdG9fbmV3ID0gZnJvbSkgJT4lIAogICAgICAgICAgICAgIHJlbmFtZShmcm9tID0gZnJvbV9uZXcsIHRvID0gdG9fbmV3KSAlPiUKICAgICAgICAgICAgICByZWxvY2F0ZShmcm9tLCB0bykpICU+JQogIGRpc3RpbmN0KGZyb20sIHRvLCAua2VlcF9hbGwgPSBUUlVFKQpgYGAKCmBgYHtyfQojIGF1Z21lbnQgcmVnaW9ucyBkYXRhIAojIE5PVEU6IERPIGVhcmxpZXIgYWxyZWFkeSBpbiBjb25zdHJ1Y3Rpb24KcmVnaW9uX1JUQSAlPD4lCiAgbXV0YXRlKGNvdW50cnkgPSBudXRzICU+JSBzdHJfc3ViKDEsMikpIApgYGAKCmBgYHtyfQojIFN1bW1hcml6ZSBSZWdpb25zCnJlZ2lvbl9SVEFfYWdnIDwtIHJlZ2lvbl9SVEEgJT4lCiAgZ3JvdXBfYnkobnV0cywgcGVyaW9kLCBZX3RhZykgJT4lCiAgc3VtbWFyaXNlKG5fc3BlYyA9IHJ0YV9iaW4gJT4lIHN1bShuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBuX3NwZWNfY291bnQgPSAobl90ZWNoX3JlZ2lvbiAqIHJ0YV9iaW4pICU+JSBzdW0obmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgSEhJID0gc3VtKChuX3RlY2hfcmVnaW9uL3N1bShuX3RlY2hfcmVnaW9uKSAqIDEwMCleMikgKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKGNvdW50cnkgPSBudXRzICU+JSBzdHJfc3ViKDEsMiksCiAgICBudXRzX3BlcmlvZCA9IHBhc3RlKG51dHMsICdQJywgcGVyaW9kKSkgCmBgYAoKYGBge3J9CiMgRGF0YWZyYW1lIHdpdGggcmVnaW9ucyBhbmQgdGVjaG5vbG9neSBmaWVsZHMKdGVjaF9kZXYgPC0gcmVnaW9uX1JUQSAlPiUKICBzZWxlY3QocGVyaW9kLCBjb3VudHJ5LCBudXRzLCBuYWNlX2dyb3VwLCBZX3RhZywgbl90ZWNoX3JlZ2lvbiwgcnRhLCBydGFfYmluKSAlPiUKICBhcnJhbmdlKG51dHMsIG5hY2VfZ3JvdXAsIFlfdGFnLCBwZXJpb2QpIAoKdGVjaF9kZXYgJTw+JSAKICBncm91cF9ieShudXRzLCBuYWNlX2dyb3VwLCBZX3RhZykgJT4lCiAgbXV0YXRlKHJ0YV9kZXYgPSBjYXNlX3doZW4oCiAgICBydGFfYmluIDwgbGFnKHJ0YV9iaW4sIDEpICB+IC0xLAogICAgcnRhX2JpbiA9PSBsYWcocnRhX2JpbiwgMSkgIH4gMCwKICAgIHJ0YV9iaW4gPiBsYWcocnRhX2JpbiwgMSkgIH4gMSAKICApKSAlPiUKICB1bmdyb3VwKCkKYGBgCgojIFBhdGVudCBhcHBsaWNhdGlvbiBkZXZlbG9wbWVudAoKKiBJbiB0aGUgZm9sbG93aW5nLCBhIGJyaWVmIGRlc2NyaXB0aXZlIGFuYWx5c2lzIG9mIHRoZSBkZXZlbG9wbWVudCBvZiBncmVlbiBhbmQgbm9uLWdyZWVuIHBhdGVudCBhcHBsaWNhdGlvbiBpbiB0aGUgTm9yZGljcwoqIEluIGFkZGl0aW9uLCBhIGJyZWFja2Rvd24gb2YgZ3JlZW4gcGF0ZW50cyBieSB0b3AgZ3JlZW4gcGF0ZW50aW5nIHJlYWdpb25zCgpgYGB7cn0KZGF0YV9hcHBsbiAlPiUKICBjb3VudChhcHBsbl9maWxpbmdfeWVhciwgWV90YWcpICU+JQogIGdncGxvdChhZXMoeCA9IGFwcGxuX2ZpbGluZ195ZWFyLCB5ID0gbiwgY29sID0gWV90YWcpKSArIAogIGdlb21fbGluZShrZXlfZ2x5cGggPSAidGltZXNlcmllcyIpICsKICBsYWJzKHRpdGxlID0gJ1BhdGVudCBhcHBsaWNhdGlvbnM6IERldmVsb3BtZW50JywKICAgICAgIHN1YnRpdGxlID0gJ0FsbCBOb3JkaWMgY29udHJpZXMsIGJ5IFkgdGFnJywKICAgICAgIHggPSAnWWVhcicsCiAgICAgICB5ID0gJ051bWJlciBhcHBsaWNhdGlvbnMnLAogICAgICAgY29sID0gJ0dyZWVuJykKYGBgCmBgYHtyfQpkYXRhX3BlcnNfYXBwbG4gJT4lCiAgc2VtaV9qb2luKHRvcF9yZWdpb25zLCBieSA9ICdudXRzJykgJT4lCiAgY291bnQoYXBwbG5fZmlsaW5nX3llYXIsIG51dHMsIFlfdGFnLCB3dCA9IHdlaWdodF9mcmFjKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBhcHBsbl9maWxpbmdfeWVhciwgeSA9IG4sIGNvbCA9IG51dHMpKSArIAogIGdlb21fbGluZShrZXlfZ2x5cGggPSAidGltZXNlcmllcyIpICsKICBmYWNldF93cmFwKHZhcnMoWV90YWcpLCBzY2FsZXMgPSAnZnJlZScpICsKICBsYWJzKHRpdGxlID0gJ1BhdGVudCBhcHBsaWNhdGlvbnM6IERldmVsb3BtZW50JywKICAgICAgIHN1YnRpdGxlID0gJ0FsbCBOb3JkaWMgY29udHJpZXMnLAogICAgICAgeCA9ICdZZWFyJywKICAgICAgIHkgPSAnTnVtYmVyIGFwcGxpY2F0aW9ucywgYnkgcmVnaW9uIGFuZCBZIHRhZycsCiAgICAgICBjb2wgPSAnTnV0czMnKQpgYGAKCiMgVGVjaG5vbG9neSBzcGFjZSBnZW5lcmFsCgoqIFdlIGNhbGN1bGF0ZSB0aGUgcmVsYXRlZG5lc3Mgb2YgaW5kdXN0cmllcyBieSBjby1vY2N1cmVuY2UgcGF0dGVybiBmb2xsb3dpbmcgSGlkYWxnbyAmIEhhdXNtYW5uICgyMDA3KQoqIFJldmVhbGVkIHRlY2hub2xvZ2ljYWwgYWR2YW50YWdlIChSVEEpIElzIHNlcHBlcmF0ZWRseSBjYWxjdWxhdGVkIGZvciBZLXRhZyBhbmQgbm9uLVktdGFnIHBhdGVudHMuCgpgYGB7cn0Kc2V0LnNlZWQoMTMzNykKY29vcmRzX3RlY2ggPC0gZ190ZWNoICU+JSBpZ3JhcGg6OmxheW91dC5mcnVjaHRlcm1hbi5yZWluZ29sZCgpICU+JSBhc190aWJibGUoKQpjb2xuYW1lcyhjb29yZHNfdGVjaCkgPC0gYygieCIsICJ5IikKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PSAxMi41fQpnX3RlY2ggJU4+JQogIG11dGF0ZShuYWNlX2dyb3VwX25hbWUgPSBuYWNlX2dyb3VwX25hbWUgJT4lIHN0cl90cnVuYyg1MCwgc2lkZSA9ICdyaWdodCcpKSAlPiUKICBnZ3JhcGgobGF5b3V0ID0gIGNvb3Jkc190ZWNoKSArIAogIGdlb21fZWRnZV9saW5rKGFlcyh3aWR0aCA9IHdlaWdodCwgYWxwaGEgPSB3ZWlnaHQpLCBjb2xvdXIgPSAiZ3JleSIpICsgCiAgZ2VvbV9ub2RlX3BvaW50KGFlcyhjb2xvdXIgPSBuYWNlX3NlY19uYW1lLCBzaXplID0gZGdyKSkgKyAKICBnZW9tX25vZGVfdGV4dChhZXMobGFiZWwgPSBuYWNlX2dyb3VwX25hbWUsIHNpemUgPSBkZ3IsIGZpbHRlciA9IHBlcmNlbnRfcmFuayhkZ3IpID49IDAuNSApLCByZXBlbCA9IFRSVUUpICsKICB0aGVtZV92b2lkKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikgKyAKICBsYWJzKHRpdGxlID0gJ0luZHVzdHJ5IFNwYWNlIChhbGwgTm9yZGljcyknLAogICAgICAgc3VidGl0bGUgPSAnTm9kZXMgPSBOQUNFIDIgSW5kdXN0cmllcy4gRWRnZXM6IFJlbGF0ZWRuZXNzJykKYGBgCgojIFJlZ2lvbmFsIHNwZWNpYWxpemF0aW9uIChSVEEpIGRldmVsb3BtZW50CgoqIENvbXBhcmlzb24gb2Ygc3BlY2lhbGl6YXRpb24gcHJvdmlkZXMgaW4gcGVyaW9kIDEgYW5kIDIKCmBgYHtyfQpwMSA8LSByZWdpb25fUlRBX2FnZyAgJT4lCiAgc2VtaV9qb2luKHRvcF9yZWdpb25zLCBieSA9ICdudXRzJykgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IFlfdGFnLCB2YWx1ZXNfZnJvbSA9IGMobl9zcGVjLCBuX3NwZWNfY291bnQsIEhISSksIHZhbHVlc19maWxsID0gMCwgbmFtZXNfcHJlZml4ID0gJ1lfdGFnXycpIAoKcDIgPC0gcDEgJT4lIAogIHNlbGVjdChwZXJpb2QsIG51dHMsIG5fc3BlY19ZX3RhZ19GQUxTRSwgbl9zcGVjX1lfdGFnX1RSVUUpICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBwZXJpb2QsIHZhbHVlc19mcm9tID0gYyhuX3NwZWNfWV90YWdfRkFMU0UsIG5fc3BlY19ZX3RhZ19UUlVFKSkKYGBgCgpgYGB7ciwgZmlnLndpZHRoPSAxMCwgZmlnLmhlaWdodD0xMH0KcDEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gbl9zcGVjX1lfdGFnX0ZBTFNFLCB5ID0gbl9zcGVjX1lfdGFnX1RSVUUpKSArCiAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IG5fc3BlY19jb3VudF9ZX3RhZ19UUlVFLCBjb2wgPSBISElfWV90YWdfVFJVRSkpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbnV0cyksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSwgYWxwaGEgPSAwLjc1KSArCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBwMiwgCiAgICAgICAgICAgICAgIGFlcyh4ID0gbl9zcGVjX1lfdGFnX0ZBTFNFXzEsCiAgICAgICAgICAgICAgICAgICB5ID0gbl9zcGVjX1lfdGFnX1RSVUVfMSwKICAgICAgICAgICAgICAgICAgIHhlbmQgPSBuX3NwZWNfWV90YWdfRkFMU0VfMiwKICAgICAgICAgICAgICAgICAgIHllbmQgPSBuX3NwZWNfWV90YWdfVFJVRV8yLAogICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEpLAogICAgICAgICAgICAgICBhbHBoYSA9IDAuMTUsCiAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgwLjUsICJjbSIpLCB0eXBlID0gImNsb3NlZCIpLAogICAgICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGxvdyA9ICJza3libHVlIiwgbWlkID0gJ3llbGxvdycsIGhpZ2ggPSAicmVkIiwgbWlkcG9pbnQgPSAxKSArCiAgbGFicyh0aXRsZSA9ICdEZXZlbG9wbWVudCBvZiBuZXcgcmVnaW9uYWwgc3BlY2lhbGl6YXRpb25zJywgCiAgICAgICBzdWJ0aXRsZSA9ICdCeSBudW1iZXIgb2YgZ3JlZW4gYW5kIG5vbiBncmVlbiBzcGVjaWFsaXphdGlvbnMgaW4gcGVyaW9kIDEgYW5kIDInLAogICAgICAgbm90ZSA9ICcnLAogICAgICAgeCA9ICdOIG5vbi1ncmVlbiBzcGVjaWFsaXphdGlvbnMnLAogICAgICAgeSA9ICdOIGdyZWVuIHNwZWNpYWxpemF0aW9ucycsCiAgICAgICBzaXplID0gJ04gZ3JlZW4gcGF0ZW50cycsCiAgICAgICBjb2wgPSAnSEhJIGdyZWVuIHBhdGVudHMnKSAKYGBgCgpgYGB7cn0Kcm0ocDIsIHAyKQpgYGAKCiMgQW5hbHlzaXMgZm9yIGV4aXN0aW5nIGdyZWVuIHBhdGhzOgoKYGBge3J9CnNlbGVjdF9yZWdpb25zX2dyZWVuIDwtIHRlY2hfZGV2ICU+JQogIGdyb3VwX2J5KG51dHMsIHBlcmlvZCkgJT4lCiAgc3VtbWFyaXNlKGdyZWVuID0gIHN1bShZX3RhZyAqIHJ0YSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgZ3JlZW5fYmluID0gIHN1bShZX3RhZyAqIHJ0YV9iaW4sIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIG5fdGVjaF9yZWdpb24gPSAgc3VtKG5fdGVjaF9yZWdpb24sIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIG5fZ3JlZW5fcmVnaW9uID0gIHN1bShZX3RhZyAqIG5fdGVjaF9yZWdpb24sIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIG5fZ3JlZW5fcnRhID0gIHN1bShZX3RhZyAqIG5fdGVjaF9yZWdpb24gKiBydGFfYmluLCBuYS5ybSA9IFRSVUUpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZmlsdGVyKG5fZ3JlZW5fcnRhID49IDEwMCwKICAgICAgICAgZ3JlZW5fYmluID49IDEsCiAgICAgICAgIHBlcmlvZCA9PSAnMScpICU+JQogIHNlbGVjdChudXRzKQpgYGAKCmBgYHtyfQp0ZWNoX3NwZWNfZGV2IDwtIHRlY2hfZGV2ICU+JQogIGZpbHRlcihuX3RlY2hfcmVnaW9uID49IDUwKSAlPiUKICBncm91cF9ieShudXRzLCBZX3RhZykgJT4lCiAgc3VtbWFyaXNlKHJ0YV9kZXYgPSBydGFfZGV2ICU+JSBzdW0obmEucm0gPSBUUlVFKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBZX3RhZywgdmFsdWVzX2Zyb20gPSBydGFfZGV2LCB2YWx1ZXNfZmlsbCA9IDAsIG5hbWVzX3ByZWZpeCA9ICdZX3NwZWNfJykKYGBgCgpgYGB7cn0KdGVjaF9yZWxfZGV2IDwtIHRlY2hfcmVsICU+JSAKICBzZWxlY3QoZnJvbSwgdG8sIHdlaWdodCkgJT4lCiAgbGVmdF9qb2luKHRlY2hfZGV2ICU+JSBkaXN0aW5jdChuYWNlX2dyb3VwLCBudXRzKSwgYnkgPSBjKCdmcm9tJyA9ICduYWNlX2dyb3VwJykpICU+JQogICMgZmlsdGVyIGZvciBydGEgaW4gcGVyaW9kIDEKICBpbm5lcl9qb2luKHRlY2hfZGV2ICU+JSBmaWx0ZXIocGVyaW9kID09ICcxJywgcnRhX2JpbiA9PSAxKSAlPiUgc2VsZWN0KG5hY2VfZ3JvdXAsIG51dHMsIFlfdGFnKSwgYnkgPSBjKCd0bycgPSAnbmFjZV9ncm91cCcsICdudXRzJykpICU+JQogICMgZmlsdGVyIGZvciBuZXcgZ3JlZW4gc3BlY2lhbGl6YXRpb24gaW4gcGVyaW9kIDIKICBzZW1pX2pvaW4odGVjaF9kZXYgJT4lIGZpbHRlcihwZXJpb2QgPT0gJzInLCBydGFfYmluID09IDEsIHJ0YV9kZXYgPT0gMSwgWV90YWcgPT0gVFJVRSksIGJ5ID0gYygnZnJvbScgPSAnbmFjZV9ncm91cCcsICdudXRzJykpICU+JQogIHJlbmFtZShuYWNlX2dyb3VwID0gZnJvbSwgcmVsYXRlZF90ZWNobiA9IHRvKSAlPiUKICBncm91cF9ieShudXRzLCBuYWNlX2dyb3VwLCBZX3RhZykgJT4lCiAgc3VtbWFyaXNlKHJlbF9tYXggPSB3ZWlnaHQgJT4lIG1heCgpLAogICAgICAgICAgICByZWxfc3VtID0gd2VpZ2h0ICU+JSBzdW0oKSwKICAgICAgICAgICAgcmVsX21lYW4gPSB3ZWlnaHQgJT4lIG1lYW4oKSkgJT4lCiAgdW5ncm91cCgpCmBgYAoKYGBge3IsIGZpZy53aWR0aD0gMTAsIGZpZy5oZWlnaHQ9MTB9CnRlY2hfcmVsX2RldiAlPiUKICBncm91cF9ieShudXRzLCBZX3RhZykgJT4lCiAgc3VtbWFyaXNlKHJlbCA9IHJlbF9tYXggJT4lIG1lYW4oKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBZX3RhZywgdmFsdWVzX2Zyb20gPSByZWwsIG5hbWVzX3ByZWZpeCA9ICdZXycsIHZhbHVlc19maWxsID0gMCkgJT4lCiAgbGVmdF9qb2luKHRlY2hfZGV2ICU+JSBmaWx0ZXIoWV90YWcgPT0gVFJVRSwgcGVyaW9kID09ICcyJywgcnRhX2JpbiA9PSAxKSAlPiUgc2VsZWN0KG51dHMgLCBuX3RlY2hfcmVnaW9uKSAlPiUgY291bnQobnV0cywgd3QgPSBuX3RlY2hfcmVnaW9uKSwgYnkgPSBjKCdudXRzJykpICU+JQogIG11dGF0ZShjb3VudHJ5ID0gbnV0cyAlPiUgc3RyX3N1YigxLDIpKSAlPiUKICAjc2VtaV9qb2luKHRvcF9yZWdpb25zLCBieSA9ICdudXRzJykgJT4lCiAgZmlsdGVyKDAuNSA8PSBwZXJjZW50X3JhbmsobikpICU+JQogIGdncGxvdChhZXMoeCA9IFlfRkFMU0UsIHkgPSBZX1RSVUUsIHNpemUgPSBuKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbCA9IGNvdW50cnkpKSArCiAgZ2VvbV90ZXh0X3JlcGVsKGFlcyhsYWJlbCA9IG51dHMpLCBib3gucGFkZGluZyA9IDAuNSwgbWF4Lm92ZXJsYXBzID0gSW5mKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArIAogICAgbGFicyh0aXRsZSA9ICdOZXcgZ3JlZW4gc3BlY2lhbGl6YXRpb24gcGVyaW9kIDInLCAKICAgICAgIHN1YnRpdGxlID0gJ0J5IG51dHMgcmVnaW9ucycsCiAgICAgICBub3RlID0gJ1JlbGF0ZWRuZXNzIGlzIHRoZSBtZWFuIG92ZXIgYWxsIG5ldyBncmVlbiBzcGVjaWFsaXphdGlvbnMsIHBlciBncmVlbiBzcGVjaWFsaXphdGlvbiBsYXJnZXN0IHJlbGF0ZWRuZXNzIHRvIGZvcm1lciBzcGVjaWFsaXphdGlvbiBjb3VudGVkJywKICAgICAgIHggPSAnUmVsYXRlZG5lc3Mgbm9uLWdyZWVuJywKICAgICAgIHkgPSAnUmVsYXRlZG5lc3MgZ3JlZW4nLAogICAgICAgc2l6ZSA9ICdOIGdyZWVuIHBhdGVudHMnKSAKYGBgCgpgYGB7ciwgZmlnLndpZHRoPSAxMCwgZmlnLmhlaWdodD0xMH0KdGVjaF9yZWxfZGV2ICU+JQogIGdyb3VwX2J5KG51dHMsIG5hY2VfZ3JvdXAsIFlfdGFnKSAlPiUKICBzdW1tYXJpc2UocmVsID0gcmVsX21heCAlPiUgbWVhbigpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IFlfdGFnLCB2YWx1ZXNfZnJvbSA9IHJlbCwgbmFtZXNfcHJlZml4ID0gJ1lfJywgdmFsdWVzX2ZpbGwgPSAwKSAlPiUKICBsZWZ0X2pvaW4odGVjaF9kZXYgJT4lIGZpbHRlcihZX3RhZyA9PSBUUlVFLCBwZXJpb2QgPT0gJzInLCBydGFfYmluID09IDEpICU+JSBzZWxlY3QobnV0cywgbmFjZV9ncm91cCwgbl90ZWNoX3JlZ2lvbikgJT4lIGNvdW50KG51dHMsIG5hY2VfZ3JvdXAsIHd0ID0gbl90ZWNoX3JlZ2lvbiksIGJ5ID0gYygnbnV0cycsICduYWNlX2dyb3VwJykpICU+JQogIG11dGF0ZShjb3VudHJ5ID0gbnV0cyAlPiUgc3RyX3N1YigxLDIpKSAlPiUKICBzZW1pX2pvaW4odG9wX3JlZ2lvbnMsIGJ5ID0gJ251dHMnKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBZX0ZBTFNFLCB5ID0gWV9UUlVFLCBzaXplID0gbikpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdGV4dF9yZXBlbChhZXMobGFiZWwgPSBuYWNlX2dyb3VwKSwgYm94LnBhZGRpbmcgPSAwLjUpICsKICBmYWNldF93cmFwKHZhcnMobnV0cykpICsKICAgIGxhYnModGl0bGUgPSAnTmV3IGdyZWVuIHNwZWNpYWxpemF0aW9uIHBlcmlvZCAyJywgCiAgICAgICBzdWJ0aXRsZSA9ICdCeSBudXRzIHJlZ2lvbnMnLAogICAgICAgbm90ZSA9ICdSZWxhdGVkbmVzcyBpcyB0aGUgbWVhbiBvdmVyIGFsbCBuZXcgZ3JlZW4gc3BlY2lhbGl6YXRpb25zLCBwZXIgZ3JlZW4gc3BlY2lhbGl6YXRpb24gbGFyZ2VzdCByZWxhdGVkbmVzcyB0byBmb3JtZXIgc3BlY2lhbGl6YXRpb24gY291bnRlZCcsCiAgICAgICB4ID0gJ1JlbGF0ZWRuZXNzIG5vbi1ncmVlbicsCiAgICAgICB5ID0gJ1JlbGF0ZWRuZXNzIGdyZWVuJywKICAgICAgIHNpemUgPSAnTiBncmVlbiBwYXRlbnRzJykgCmBgYAoKIyBUT0RPCgoqIExhYmVsIDJuZCBmaWd1cmUgb24gZ3JlZW4sIGxhYmVsIGNvaW5jaWRpbmcsIG1heWJlIHJ0YSwgc2hhcmUgb3IgZ3Jvd3RoCiogRG8gc29tZSByYWRhciBwbG90dGluZywgZWc6IGh0dHBzOi8vci1ncmFwaC1nYWxsZXJ5LmNvbS93ZWItY2lyY3VsYXItYmFycGxvdC13aXRoLVItYW5kLWdncGxvdDIuaHRtbCAKCmBgYHtyfQpzZXNzaW9uSW5mbygpCmBgYAoKCg==